package com.lxm.ymcc.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.lxm.ymcc.constans.Mq;
import com.lxm.ymcc.domain.CourseOrder;
import com.lxm.ymcc.domain.CourseOrderItem;
import com.lxm.ymcc.dto.CourseItemVo;
import com.lxm.ymcc.dto.CourseOrderDataVo;
import com.lxm.ymcc.dto.MqOrder;
import com.lxm.ymcc.dto.OrderDto;
import com.lxm.ymcc.feginClient.CourserFileFeign;
import com.lxm.ymcc.mapper.CourseOrderMapper;
import com.lxm.ymcc.result.JSONResult;
import com.lxm.ymcc.service.ICourseOrderItemService;
import com.lxm.ymcc.service.ICourseOrderService;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.lxm.ymcc.util.AssertUtil;
import com.lxm.ymcc.util.CodeGenerateUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.client.producer.SendStatus;
import org.apache.rocketmq.client.producer.TransactionSendResult;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author whale
 * @since 2022-11-02
 */
@Service
@Slf4j
public class CourseOrderServiceImpl extends ServiceImpl<CourseOrderMapper, CourseOrder> implements ICourseOrderService {
    @Autowired
    private RedisTemplate<Object,Object > redisTemplate;
    @Autowired
    private CourserFileFeign courserFileFeign;
    @Autowired
    private ICourseOrderItemService courseOrderItemService;

    @Autowired
    private RocketMQTemplate rocketMQTemplate;


    @Override
    public String placeOrder(OrderDto orderDto) {


        Long loginId = 3l;
        //   1.校验token是否正确
        String ids = StringUtils.join(orderDto.getCourseIds(),",");
        // 设置的token值 是用户 加商品的id‘
        Object o = redisTemplate.opsForValue().get(loginId + ":" + ids);
        AssertUtil.isNotNull(o,"订单已经创建");
        String tokenRedis = o.toString();
        AssertUtil.isEqualsTrim(orderDto.getToken(),tokenRedis,"订单已经创建");

        //  2.通过fegin接口调用的course获取数据
        JSONResult jsonResult = courserFileFeign.courseInfo(ids);
        AssertUtil.isTrue(jsonResult.isSuccess(),jsonResult.getMessage());

        // 进行转换
        String jsonString = JSON.toJSONString(jsonResult.getData());

        // 还原数据
        CourseOrderDataVo courseOrderDataVo = JSONObject.parseObject(jsonString, CourseOrderDataVo.class);

        //4.生成的order
        CourseOrder order = new CourseOrder();
        order.setCreateTime(new Date());
        /*
            订单编号--系统唯一
         */
        String orderSn = CodeGenerateUtils.generateOrderSn(loginId);
        order.setOrderNo(orderSn);
        /**
         * 支付总的价格
         */
        order.setTotalAmount(courseOrderDataVo.getTotalAmount());
        /**
         * 优惠金额
         */
        order.setDiscountAmount(new BigDecimal("0"));
        /**
         * 支付金额
         */
        order.setPayAmount(order.getTotalAmount().subtract(order.getDiscountAmount()));

        /**
         * 秒杀数量
         */
        order.setTotalCount(1);
        order.setStatusOrder(CourseOrder.PLACE_ORDER_OK);
        order.setUserId(loginId);
        /**
         * 订单标题
         */
        order.setTitle("购买课程下单");
        order.setVersion(0);
        /**
         * 支付方式:0余额直接，1支付宝，2微信,3银联
         */
        order.setPayType(orderDto.getPayType());
        /**
         * 0普通订单 ， 1秒杀订单
         */
        order.setOrderType(orderDto.getType());

        //5.保存数据  返回数据的主键
        // insert(order);
        List<CourseItemVo> list = courseOrderDataVo.getList();
        list.forEach(courseItemVo -> {
            CourseOrderItem item = new CourseOrderItem();
            item.setAmount(courseItemVo.getCourseMarket().getPrice());
            item.setCount(1);
            item.setCreateTime(new Date());
            item.setCourseId(courseItemVo.getCourse().getId());
            item.setCourseName(courseItemVo.getCourse().getName());
            item.setCoursePic(courseItemVo.getCourse().getPic());
            item.setVersion(0);
            item.setOrderNo(orderSn);
            item.setKillCourseId(0L);
            // item.setOrderId(order.getId());
            //保存订单明细
           order.getItems().add(item);
        });
        //发送事务消息
        /*
         * @param txProducerGroup 事务组的名称，监听事务状态 要使用
         * @param destination     目的地 formats: `topicName:tags`
         * @param message         消息体
         * @param arg             额外的参数
         * @return TransactionSendResult
         * extParams :{"userId":3,"courseIds":ids}
         */
        Map<String,Object> map  = new HashMap<>();
        map.put("userId",loginId);
        map.put("courseIds",ids);


        //------------ 发送事物消息
            // 封装mq里面的消息体
        MqOrder mqOrder = new MqOrder(order.getPayAmount(), order.getPayType(), orderSn, loginId, JSON.toJSONString(map), order.getTitle());

        Message<MqOrder> message = MessageBuilder.withPayload(mqOrder).build();
        TransactionSendResult sendResult = rocketMQTemplate.sendMessageInTransaction(Mq.PRODUCE_GROUP, Mq.ORDER_TOPIC + ":" + Mq.ORDER_TAGS, message, order);
        AssertUtil.isTrue(sendResult.getSendStatus().equals(SendStatus.SEND_OK),"消息发送失败");



        Message<String> msg = MessageBuilder.withPayload(orderSn).build();
        //添加定时任务【延时消息实现】
        SendResult result = rocketMQTemplate.syncSend("topic-order-cancel:tags-order-cancel", msg, 3000, 4);//30s
        if(!result.getSendStatus().equals(SendStatus.SEND_OK)){
            //
            log.info("消息投递失败：{}",result);
        }

        //移除redis里面的key
        redisTemplate.delete(loginId+":"+ids);

        return orderSn;
    }

    @Override
    @Transactional
    public void saveOnOrder(CourseOrder courseOrder) {
        // 保存courseOrder 数据
        insert(courseOrder);

        List<CourseOrderItem> items = courseOrder.getItems();
        items.forEach(item->{
            // 设置id
           item.setOrderId(courseOrder.getId());
            // 保存订单明细表
            courseOrderItemService.insert(item);
        });
    }

    @Override
    public CourseOrder selectOneOrSn(String orderNo) {
        Wrapper<CourseOrder> wrapper = new EntityWrapper<>();
        wrapper.eq("order_no",orderNo);

        return selectOne(wrapper);
    }

    @Override
    public void cancelOrder(String orderSn) {
        //根据订单查询订单
        CourseOrder courseOrder = selectOneOrSn(orderSn);
        //判断订单是否需要取消
        if(courseOrder!=null&&courseOrder.getStatusOrder()==0){
            //超时取消订单
            courseOrder.setStatusOrder(4);
            courseOrder.setUpdateTime(new Date());
            updateById(courseOrder);
        }

    }

}


